<template>
  <div ref="wrapper" class="list-wrapper">
    <div>
      <slot>
        <ul class="list-content">
          <li @click="clickItem(item)" class="list-item" v-for="item in data">{{item}}</li>
        </ul>
      </slot>
      <slot name="pullup"
            :pullUpLoad="pullUpLoad"
            :isPullUpLoad="isPullUpLoad">
        <div class="pullup-wrapper" v-if="pullUpLoad">
          <div class="before-trigger" v-if="!isPullUpLoad">
            <span>加载更多</span>
          </div>
          <div class="after-trigger" v-else>
            <Spinner type="triple-bounce" color="#26a2ff" :size="20"></Spinner>
          </div>
        </div>
      </slot>
    </div>
    <slot name="pulldown"
          :pullDownRefresh="pullDownRefresh"
          :pullDownStyle="pullDownStyle"
          :beforePullDown="beforePullDown"
          :pulling="pulling">
      <div ref="pulldown" class="pulldown-wrapper" :style="pullDownStyle" v-if="pullDownRefresh">
        <div class="before-trigger" v-if="beforeTriggerShow">
          下拉刷新...
        </div>
        <div class="after-trigger" v-else>
          <div v-if="pulling" class="scroller_loading">
            <Spinner type="double-bounce" color="#26a2ff" :size="20"></Spinner>
          </div>
          <!--<div v-else><span>刷新成功</span></div>-->
        </div>
      </div>
    </slot>
    <div class="scroll-toast" v-show="pulling"></div>
  </div>

</template>

<script type="text/ecmascript-6">
  import BScroll from 'better-scroll';
  import {Spinner, Toast} from 'mint-ui';

  const COMPONENT_NAME = 'scroll-list';
  const DIRECTION_H = 'horizontal';
  const DIRECTION_V = 'vertical';

  export default {
    name: COMPONENT_NAME,
    props: {
      data: {
        type: Array,
        default: []
      },
      probeType: {
        type: Number,
        default: 1
      },
      click: {
        type: Boolean,
        default: false
      },
      listenScroll: {
        type: Boolean,
        default: false
      },
      listenBeforeScroll: {
        type: Boolean,
        default: false
      },
      direction: {
        type: String,
        default: DIRECTION_V
      },
      scrollbar: {
        type: null,
        default: false
      },
      pullDownRefresh: {
        type: null,
        default: false
      },
      pullUpLoad: {
        type: null,
        default: false
      },
      startY: {
        type: Number,
        default: 0
      },
      refreshDelay: {
        type: Number,
        default: 20
      }
    },
    data() {
      return {
        beforePullDown: true,
        isRebounding: false,
        isPullingDown: false,
        pulling: false,
        isPullUpLoad: false,
        pullDownStyle: ''
      };
    },
    created() {
      this.pullDownInitTop = -50;
    },
    mounted() {
      setTimeout(() => {
        this.initScroll();
      }, 20);
    },
    methods: {
      initScroll() {
        if (!this.$refs.wrapper) {
          return;
        }

        let options = {
          probeType: this.probeType,
          click: this.click,
          scrollY: this.direction === DIRECTION_V,
          scrollX: this.direction === DIRECTION_H,
          scrollbar: this.scrollbar,
          pullDownRefresh: this.pullDownRefresh,
          pullUpLoad: this.pullUpLoad,
          startY: this.startY
        };

        this.scroll = new BScroll(this.$refs.wrapper, options);

        if (this.listenScroll) {
          this.scroll.on('scroll', (pos) => {
            this.$emit('scroll', pos);
          });
        }

        if (this.listenBeforeScroll) {
          this.scroll.on('beforeScrollStart', () => {
            this.$emit('beforeScrollStart');
          });
        }

        if (this.pullDownRefresh) {
          this._initPullDownRefresh();
        }

        if (this.pullUpLoad) {
          this._initPullUpLoad();
        }
      },
      disable() {
        this.scroll && this.scroll.disable();
      },
      enable() {
        this.scroll && this.scroll.enable();
      },
      refresh() {
        this.scroll && this.scroll.refresh();
      },
      scrollTo() {
        this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments);
      },
      scrollToElement() {
        this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments);
      },
      clickItem(item) {
        this.$emit('click', item);
      },
      destroy() {
        this.scroll.destroy();
      },
      _initPullDownRefresh() {
        this.scroll.on('pullingDown', () => {
          this.$emit('pullingDown');
          this.beforePullDown = false;
          this.isPullingDown = true;
          this.pulling = true;
          this.scroll.disable();
        });

        this.scroll.on('scroll', (pos) => {
          let top = 0;
          if (this.pullDownRefresh.threshold) {
            top = parseInt(this.pullDownRefresh.threshold);
          } else {
            top = parseInt(-this.pullDownInitTop);
          }
          if (pos.y > top) {
            if (this.beforePullDown) {
              this.pullDownStyle = `top:${Math.min(pos.y + this.pullDownInitTop, 10)}px`;
            }
            if (this.isRebounding) {
              this.pullDownStyle = `top:${10 - (this.pullDownRefresh.stop - pos.y)}px`;
            }
          }
        });
      },
      _initPullUpLoad() {
        this.scroll.on('pullingUp', () => {
          this.$emit('pullingUp');
          this.isPullUpLoad = true;
        });
      },
      _reboundPullDown() {
        const {stopTime = 600} = this.pullDownRefresh;
        return new Promise((resolve) => {
          setTimeout(() => {
            this.isRebounding = true;
            this.scroll.finishPullDown();
            this.isPullingDown = false;
            resolve();
          }, stopTime);
        });
      },
      _afterPullDown() {
        setTimeout(() => {
          this.pullDownStyle = `top:${this.pullDownInitTop}px`;
          this.beforePullDown = true;
          this.isRebounding = false;
          this.refresh();
        }, this.scroll.options.bounceTime);
      }
    },
    watch: {
      data() {
        setTimeout(() => {
          if (this.pullDownRefresh && this.isPullingDown) {
            this.pulling = false;
            this.scroll.enable();
            //  提示
            Toast({
              message: '刷新成功',
              duration: 2000
            });
            this._reboundPullDown().then(() => {
              this._afterPullDown();
            });
          } else if (this.pullUpLoad && this.isPullUpLoad) {
            this.isPullUpLoad = false;
            this.scroll.finishPullUp();
            this.refresh();
          } else {
            this.refresh();
          }
        }, this.refreshDelay);
      }
    },
    components: {
      Spinner
    },
    computed: {
      beforeTriggerShow() {
        return this.beforePullDown && !this.scroller_loading;
      }
    }
  };

</script>

<style scoped lang="stylus" rel="stylesheet/stylus">
  .list-wrapper
    position: relative
    top: 0
    bottom: 0
    width 100%
    height 100%
    overflow: hidden
    color rgb(147, 153, 159)
    background #f3f5f7
    .scroll-toast
      position: absolute
      left: 0
      top: 0
      right: 0
      bottom: 0
      height 100%
      z-index 9999
      background-color transparent
    .list-content
      position: relative
      z-index: 20
      background: #fff
      .list-item
        height: 60px
        line-height: 60px
        font-size: 18px
        padding-left: 20px
        border-bottom: 1px solid #e5e5e5
    .pulldown-wrapper
      position: absolute
      width: 100%
      left: 0
      display: flex
      justify-content center
      align-items center
      transition: all
      .before-trigger
        z-index: 10
    .pullup-wrapper
      width: 100%
      display: flex
      justify-content center
      align-items center
      padding: 16px 0

</style>
